package com.am.server.api.system.role.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.am.server.api.system.permission.service.PermissionService;
import com.am.server.api.system.permission.service.UserPermissionCacheService;
import com.am.server.api.system.role.dao.rdb.RoleDao;
import com.am.server.api.system.role.model.dto.*;
import com.am.server.api.system.role.model.entity.RoleEntity;
import com.am.server.api.system.role.model.mapper.RoleMapper;
import com.am.server.api.system.role.service.RoleService;
import com.am.server.common.annotation.transaction.Commit;
import com.am.server.common.annotation.transaction.ReadOnly;
import com.am.server.common.base.model.dto.PageDto;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 阮雪峰
 */
@Service
public class RoleServiceImpl implements RoleService {

    private final RoleDao roleDao;
    private final UserPermissionCacheService userPermissionCacheService;
    private final RoleMapper roleMapper;

    private final PermissionService permissionService;

    public RoleServiceImpl(RoleDao roleDao, UserPermissionCacheService userPermissionCacheService, RoleMapper roleMapper, PermissionService permissionService) {
        this.roleDao = roleDao;
        this.userPermissionCacheService = userPermissionCacheService;
        this.roleMapper = roleMapper;
        this.permissionService = permissionService;
    }

    @ReadOnly
    @Override
    public PageDto<RoleDto> find(RoleListQueryDto query) {
        Page<RoleEntity> page = roleDao.findAll(query);
        List<RoleDto> rows = page.getContent().stream().map(roleMapper::toDto).toList();
        rows.forEach(item -> permissionService.findById(item.getHomePageId()).ifPresent(menu -> item.setHomePageTitle(menu.getMeta().getTitle())));
        return new PageDto<RoleDto>()
                .setPage(query.getPage())
                .setPageSize(query.getPageSize())
                .setTotal((int) page.getTotalElements())
                .setTotalPage(page.getTotalPages())
                .setRows(rows);
    }

    @Commit
    @Override
    public void save(SaveRoleDto dto) {
        RoleEntity role = roleMapper.saveDtoToEntity(dto);
        roleDao.save(role);
    }

    @Commit
    @Override
    public void update(UpdateRoleDto dto) {
        roleDao.findById(dto.getId())
                .ifPresent(role -> {
                    BeanUtil.copyProperties(dto, role, "id");
                    roleDao.save(role);
                });
    }

    @Commit
    @Override
    public void delete(Long id) {
        roleDao.deleteById(id);
        userPermissionCacheService.refresh(StpUtil.getLoginIdAsLong());
    }

    @ReadOnly
    @Override
    public List<SimpleRoleDto> findAll() {
        return roleDao.findAllOrderByIdDesc()
                .stream()
                .map(roleMapper::toSimpleDto)
                .toList();
    }

    @Override
    public void updatePermissions(UpdateRolePermissionDto dto) {
        roleDao.findById(dto.getId())
                .ifPresent(role -> roleDao.save(role.setPermissions(dto.getPermissions())));
    }

    @Override
    public List<String> findPermissions(Long id) {
        return roleDao.findById(id)
                .map(RoleEntity::getPermissions)
                .orElse(new ArrayList<>());
    }
}
